package client

import (
	"DB/HttpVPN/http"
	"bufio"
	"bytes"
	"encoding/binary"
	"fmt"
	"net"
	"strconv"
	"strings"
)

type Transponder struct {
	serverConn   net.Conn
	client       *Client
	dataBuffer   bytes.Buffer
	bufferReader *bufio.Reader
	requestChan  chan *http.Request
}

func (this *Transponder) readResponseLine() {

}

func (this *Transponder) Repeat(req *http.Request) {
	this.requestChan <- req
}

func (this *Transponder) RecvData() {
	res := http.CreateResponse()
	this.RecvResponseLine(res)
	this.RecvResponseHeader(res)
	sendReq := this.RecvBody(res)
	if sendReq {
		this.client.responseChan <- res
	}
}

func (this *Transponder) Repeat2Client() {
	for {
		req := <-this.requestChan
		this.serverConn.Write(req.Encode())
	}
}

func (this *Transponder) RecvBody(res *http.Response) bool {
	length := res.Header.GetContentLength()
	if length >= 0 {
		bodyData := make([]byte, length)
		this.bufferReader.Read(bodyData)
		res.Body.Write(bodyData)
		return true
	}
	transferEncoding := res.Header.Get(http.TransferEncoding)
	if len(transferEncoding) <= 0 {
		return true
	}
	this.client.clientConn.Write(res.Encode())
	for {
		lineBytes, prefix, _ := this.bufferReader.ReadLine()
		chunkSizeHexStr := string(lineBytes)
		if prefix == true {
			for true {
				line, isPrefix, err := this.bufferReader.ReadLine()
				if err != nil {
					panic(err)
				}

				chunkSizeHexStr += string(line)

				if isPrefix == false {
					break
				}
			}
		}

		this.client.clientConn.Write([]byte(chunkSizeHexStr + http.CRTL))
		if chunkSizeHexStr == "" {
			break
		}

		chunkSize, err := strconv.ParseInt(chunkSizeHexStr, 16, 32)

		if err != nil {
			fmt.Println(err)
			return false
		}

		if chunkSize == 0 {
			break
		}
		data := make([]byte, chunkSize+2)

		err = binary.Read(this.bufferReader, binary.BigEndian, data)
		if err != nil {
			fmt.Println(err)
		}

		this.client.clientConn.Write(data)
	}
	return false
}

func (this *Transponder) RecvResponseHeader(res *http.Response) {
	for {
		httpLine := ""
		line, prefix, err := this.bufferReader.ReadLine()
		if err != nil {
			panic(err)
		}
		if len(line) == 0 {
			break
		}
		httpLine += string(line)
		if prefix != false {
			line, prefix, err = this.bufferReader.ReadLine()
			httpLine += string(line)
		}

		split := strings.Split(httpLine, ":")
		key := split[0]
		value := []byte(httpLine)

		tempValue := value[len(key)+2:]

		v := strings.Split(string(tempValue), ";")

		for i := 0; i < len(v); i++ {
			if i == 0 {
				res.Header.Set(key, v[i])
				continue
			}
			res.Header.Add(key, v[i])
		}
	}

}

func (this *Transponder) RecvResponseLine(res *http.Response) {
	startLineByte, prefix, _ := this.bufferReader.ReadLine()
	startLine := string(startLineByte)

	if prefix == true {
		for true {
			line, isPrefix, err := this.bufferReader.ReadLine()
			if err != nil {
				panic(err)
			}

			startLine += string(line)

			if isPrefix == false {
				break
			}
		}
	}

	split := strings.Split(startLine, " ")
	res.ResponseLine.HttpVersion = split[0]
	res.ResponseLine.StatusCode = split[1]
	res.ResponseLine.StatusDesc = split[2]
}

func CreateTransponder(client *Client) *Transponder {
	transponder := &Transponder{}
	transponder.client = client
	transponder.requestChan = make(chan *http.Request, 1024)
	dial, err := net.Dial("tcp", "14.215.177.38:80")
	transponder.serverConn = dial
	transponder.bufferReader = bufio.NewReader(dial)
	if err != nil {
		panic(err)
	}
	go transponder.RecvData()
	go transponder.Repeat2Client()
	return transponder
}
